package hello

import (
	"log"
	"time"
)

/*
1. defer后面的函数在defer语句所在的函数执行结束的时候会被调用
2. 多条defer指令，他们的执行顺序是反序
3. defer函数的参数是在defer语句出现的位置做计算的，而不是在函数运行的时候做计算的，即不是所在函数结束的时候计算的。
4. defer函数可以影响宿主函数的返回值
*/

func DeferTest() {

	var i int = 100
	foo1(i)
	foo2(i)
	foo3(i)

	i = 100
	log.Println("foo4_1 return: ", foo4_1(&i))
	i = 100
	log.Println("foo4_2 return: ", foo4_2(&i))

}

func foo1(n int) int {
	log.Println("------------ Defer  Test1 () -------------- 函数中多条defer语句顺序")
	log.Println("a a a a a")
	defer log.Println("1111")
	time.Sleep(1 * time.Second)

	log.Println("b b b b")
	defer log.Println("2222")
	time.Sleep(1 * time.Second)

	log.Println("c c c c")
	defer log.Println("3333")
	time.Sleep(1 * time.Second)
	return n
}

func foo2(n int) int {
	log.Println("------------ Defer  Test2 () -------------- 在defer语句出现的位置做计算")
	log.Println("n1=", n)
	defer log.Println("n=", n)
	n += 100
	log.Println("n2=", n)
	return n
}

// defer 中使用多条语句
func foo3(n int) int {
	log.Println("------------ Defer  Test3 () --------------defer中执行多条语句")
	log.Println("n1=", n)
	defer func() {
		n += 100
		log.Println("game over! ")
		log.Println("n=", n)
	}()
	n += 100
	log.Println("n2=", n)
	return n
}

// defer 不影响返回值
func foo4_1(i *int) int {
	log.Println("------------ Defer  Test3 () --------------  defer不影响返回值")
	*i += 100
	defer func() { *i += 200 }()
	log.Printf("i=%d", *i)
	return *i
}

// defer 影响返回值
func foo4_2(i *int) (r int) {
	log.Println("------------ Defer  Test3 () --------------  defer影响返回值")
	*i += 100
	defer func() { r += 200 }()
	log.Printf("i=%d", *i)
	return *i
}
